from iClouds.apiSerializers import *
from iClouds.apiExceptions import *
from iClouds.aesSDK import EncryptDate
import json
from zoneinfo import ZoneInfo
from django_celery_beat.models import (
    IntervalSchedule,
    CrontabSchedule,
    PeriodicTask,
    PeriodicTasks,
    ClockedSchedule,
)

# 更新计数器
# PeriodicTasks.update_changed()


class taskSyncfromIDSerializer(serializers.Serializer):
    event = CharField(
        allow_blank=True, allow_null=True, max_length=255, help_text="任务ID"
    )

    class Meta:
        fields = "__all__"


class wxappLoginSerializer(serializers.Serializer):
    """微信小程序登录"""

    code = CharField(
        allow_blank=True, allow_null=True, max_length=255, help_text="code"
    )
    refr = IntegerField(allow_null=True, required=False, help_text="推荐人ID")

    class Meta:
        fields = "__all__"


class wxRequestLoginTokenSerializer(serializers.Serializer):
    """查询扫码登录本地Token"""

    state = CharField(
        allow_blank=True, allow_null=True, max_length=255, help_text="预留验证码"
    )

    class Meta:
        fields = "__all__"


class wxChangeLoginTokenSerializer(serializers.Serializer):
    """查询扫码登录本地Token"""

    openid = CharField(
        allow_blank=True, allow_null=True, max_length=255, help_text="openid"
    )

    class Meta:
        fields = "__all__"


class WeChatSelfMenuSetSerializer(serializers.Serializer):
    data = JSONField(help_text="json对象")

    class Meta:
        fields = "__all__"


class WeChatUserinfoSerializer(serializers.ModelSerializer):
    id = IntegerField(label="ID", read_only=True)
    nickname = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="昵称",
    )
    sex = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="性别",
    )
    province = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="province",
    )
    city = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="城市",
    )
    country = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="country",
    )
    headimgurl = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="头像",
    )
    privilege = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="privilege",
    )
    source = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="source",
    )
    openid = CharField(
        read_only=True,
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        validators=[UniqueValidator(queryset=AllinpayWxchatList.objects.all())],
    )

    unionid = CharField(
        read_only=True,
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        validators=[UniqueValidator(queryset=AllinpayWxchatList.objects.all())],
    )
    userid = IntegerField(
        read_only=True,
        allow_null=True,
        max_value=2147483647,
        min_value=-2147483648,
        required=False,
    )
    status = IntegerField(
        read_only=True,
        allow_null=True,
        max_value=2147483647,
        min_value=-2147483648,
        required=False,
    )
    creattime = DateTimeField(read_only=True, allow_null=True, required=False)
    lasttime = DateTimeField(read_only=True, allow_null=True, required=False)

    class Meta:
        model = AllinpayWxchatList
        fields = [
            "id",
            "openid",
            "nickname",
            "sex",
            "province",
            "city",
            "country",
            "headimgurl",
            "privilege",
            "source",
            "unionid",
            "userid",
            "status",
            "creattime",
            "lasttime",
        ]


class wxConnectActSerializer(serializers.Serializer):
    act = ChoiceField(
        choices=("start", "stop", "exit"), help_text="任务代码 start|stop|exit"
    )

    class Meta:
        fields = "__all__"


class AllinpayDeviceLicenseSerializer(serializers.ModelSerializer):
    id = IntegerField(label="ID", read_only=True)
    serialid = CharField(
        allow_blank=True, allow_null=True, max_length=255, help_text="设备序列号"
    )
    name = CharField(
        allow_blank=True, allow_null=True, max_length=255, help_text="项目名称"
    )
    cipher = CharField(
        allow_blank=True, allow_null=True, max_length=16, help_text="密钥"
    )
    ciphertext = CharField(
        allow_blank=True,
        allow_null=True,
        max_length=255,
        required=False,
        help_text="密文",
    )
    over = DateTimeField(allow_null=True, help_text="有效期")
    creattime = DateTimeField(read_only=True, allow_null=True, help_text="创建时间")
    answer = IntegerField(read_only=True, allow_null=True, help_text="创建者")

    class Meta:
        model = AllinpayDeviceLicense
        fields = "__all__"

    def validate(self, attrs):
        attrs = dict(attrs)
        if not attrs.get("cipher"):
            raise MyBaseError("密钥不能为空")
        if not attrs.get("serialid"):
            raise MyBaseError("设备序列号不能为空")
        if not attrs.get("name"):
            raise MyBaseError("项目名称不能为空")
        if not attrs.get("over"):
            raise MyBaseError("有效期不能为空")
        # key的长度需要补长(16倍数),补全方式根据情况而定,未补齐会报错
        # key字符长度决定加密结果,长度16：加密结果AES(128),长度32：结果就是AES(256)
        plaintext = f'{attrs.get("serialid")}|{attrs.get("name")}|{attrs.get("over")}'
        eg = EncryptDate(attrs.get("cipher"))
        # 加密字符串长同样需要16倍数：需注意,不过代码中pad()方法里，帮助实现了补全（补全方式就是pkcs7）
        en = eg.encrypt(plaintext)
        de = eg.decrypt(en)
        print(f"加密结果：{en}")
        print(f"解密结果：{de}")

        attrs["ciphertext"] = en
        return attrs


# =========================================================================
# 订阅事件
# =========================================================================


class DjangoCeleryBeatCrontabscheduleSerializer(serializers.Serializer):
    """cron时间"""

    id = IntegerField(label="ID", read_only=True)
    minute = CharField(max_length=240, default="5", help_text="分钟(* | 0-59)")
    hour = CharField(max_length=96, default="*", help_text="小时(* | 0-23)")
    day_of_week = CharField(
        max_length=64, default="*", help_text="日/周(* | 0-6) Sunday=0"
    )
    day_of_month = CharField(max_length=124, default="*", help_text="日/月(* | 1-30)")
    month_of_year = CharField(max_length=64, default="*", help_text="月/年(* | 1-12)")
    timezone = CharField(
        max_length=63, default=ZoneInfo("Asia/Shanghai"), help_text="时区"
    )

    class Meta:
        model = CrontabSchedule
        fields = "__all__"

    def create(self, validated_data):
        print(validated_data)
        return CrontabSchedule.objects.create(**validated_data)


class DjangoCeleryBeatIntervalscheduleSerializer(serializers.Serializer):
    id = IntegerField(label="ID", read_only=True)
    every = IntegerField(min_value=1, help_text="频率")
    period = ChoiceField(
        choices=("Days", "Hours", "Minutes", "Seconds", "Microseconds"),
        help_text="时间单位(Days | Hours | Minutes | Seconds | Microseconds)",
    )

    class Meta:
        model = IntervalSchedule
        fields = "__all__"

    def create(self, validated_data):
        period = self.has_period(validated_data["period"])
        return IntervalSchedule.objects.create(
            every=validated_data["every"], period=period
        )

    def has_period(self, val):
        """枚举类型"""
        if val == "Days":
            return IntervalSchedule.DAYS
        elif val == "Hours":
            return IntervalSchedule.HOURS
        elif val == "Minutes":
            return IntervalSchedule.MINUTES
        elif val == "Seconds":
            return IntervalSchedule.SECONDS
        elif val == "Microseconds":
            return IntervalSchedule.MICROSECONDS
        else:
            raise ValidationError("字段错误的值")


class DjangoCeleryBeatPeriodictaskSerializer(serializers.ModelSerializer):
    # id = IntegerField(label="ID", read_only=True)
    # name = CharField(
    #     max_length=200,
    #     validators=[
    #         UniqueValidator(queryset=DjangoCeleryBeatPeriodictask.objects.all())
    #     ],
    # )
    # task = CharField(max_length=200)
    # args = CharField(style={"base_template": "textarea.html"})
    # kwargs = CharField(style={"base_template": "textarea.html"})
    # queue = CharField(allow_blank=True, allow_null=True, max_length=200, required=False)
    # exchange = CharField(
    #     allow_blank=True, allow_null=True, max_length=200, required=False
    # )
    # routing_key = CharField(
    #     allow_blank=True, allow_null=True, max_length=200, required=False
    # )
    # expires = DateTimeField(allow_null=True, required=False)
    # enabled = IntegerField(max_value=2147483647, min_value=-2147483648)
    # last_run_at = DateTimeField(allow_null=True, required=False)
    # total_run_count = IntegerField(max_value=4294967295, min_value=0)
    # date_changed = DateTimeField()
    # description = CharField(style={"base_template": "textarea.html"})
    # one_off = IntegerField(max_value=2147483647, min_value=-2147483648)
    # start_time = DateTimeField(allow_null=True, required=False)
    # priority = IntegerField(
    #     allow_null=True, max_value=4294967295, min_value=0, required=False
    # )
    # headers = CharField(style={"base_template": "textarea.html"})
    # expire_seconds = IntegerField(
    #     allow_null=True, max_value=4294967295, min_value=0, required=False
    # )

    # crontab = PrimaryKeyRelatedField(allow_null=True, queryset=DjangoCeleryBeatCrontabschedule.objects.all(), required=False)
    # interval = PrimaryKeyRelatedField(allow_null=True, queryset=DjangoCeleryBeatIntervalschedule.objects.all(), required=False)
    # solar = PrimaryKeyRelatedField(allow_null=True, queryset=DjangoCeleryBeatSolarschedule.objects.all(), required=False)
    # clocked = PrimaryKeyRelatedField(allow_null=True, queryset=DjangoCeleryBeatClockedschedule.objects.all(), required=False)

    model = SerializerMethodField()
    users = SerializerMethodField()
    # answer = SerializerMethodField()

    class Meta:
        model = PeriodicTask
        fields = "__all__"

    def get_model(self, attr):
        try:
            d = json.loads(attr.kwargs)
            r = AllinpayRobotModels.objects.get(id=d["event"])
        except BaseException as err:
            return ""
        else:
            return r.name, r.mode

    def get_users(self, attr):
        try:
            d = json.loads(attr.kwargs)
            r = AllinpayRobotList.objects.get(id=d["usert"])
        except BaseException as err:
            return ""
        else:
            return r.basename, r.nicename


# print(repr(DjangoCeleryBeatPeriodictaskSerializer()))
